/*===========================================================
 
 .---=||||[ B L O O D Y ]|||||=====================----------....
 |                                                              |
 |    THE  M O S T   B L O O D Y  GAME EVER!                    |
 |                                                              |
 |    bloody harvest is coming... soon,                         |
 |                                              heil Satan!     |
 !                                                              !
 .                                                              ,
  ~~~~-------------================================|||||||||==-~




 Name-Space: {core, logic, editor}
 Module: {draw, coll, scgr, ...}
 Class: <name of class>
 Last modification:  <author>, <time>

 TODO:
 <-------- todo #1 ---------->
 <-------- todo #2 ---------->
 <-------- todo #3 ---------->
        ............
 <-------- todo #n ---------->

 FIX:
 <-------- fix #1 ----------->
 <-------- fix #1 ----------->
         ..........
 <-------- fix #n ----------->




 
 
 ============================================================*/
///////////////////////////////////////////////////////////////////////////////
//
// Pop Zombie Game
// 
// Font class implementation file
// 
///////////////////////////////////////////////////////////////////////////////

#include <cstdarg>
#include <cstdlib>
#include <fstream>
#include <iostream>

#include "core/exceptions.h"
#include "core/draw/TextureManager.h"
#include "core/draw/Font.h"

using namespace std;

namespace core
{
	namespace draw
	{
	
		Font::Font(string txtFile, string textureFileName):
			fontTexture(*TextureManager::instance().get(textureFileName))
		{
			loadGlyphs(txtFile);
			buildGlyphs();
		}
		
		Font::~Font()
		{
			glDeleteLists(fontBase, 95);	
		}
		
		void Font::loadGlyphs(string txtFile)
		{
			ifstream fs(txtFile.c_str());
			if (!fs.good())
				throw FileNotFoundException(txtFile.c_str());
			
			char ch;
			int dim;
			fs >> dim;
			// read trailing end of line
			fs.get(ch);
			
			
			for (unsigned i = 0; i < 95; i++)
			{
				char ch;
				int x,y,w,h;
				fs.get(ch);
				fs >> x >> y >> w >> h;
				// read trailing end of line
				fs.get(ch);
				glyphs[i].p1.x = x / (float) dim;
				glyphs[i].p1.y = y / (float) dim;
				glyphs[i].p2.x = w / (float) dim;
				glyphs[i].p2.y = h / (float) dim;
				glyphs[i].p2 += glyphs[i].p1;
				
				glyphs[i].w = w;
				glyphs[i].h = h;
				
				//cerr << x << "," << y << " " << w << "," << h << endl;
			}
			
			fs.close();
		}
		
		void Font::buildGlyphs()
		{
			fontBase = glGenLists(95);
			for (int i = 0; i < 95; i++)
			{
				const Glyph& g = glyphs[i];
				
				glNewList(fontBase + i, GL_COMPILE);
				glBegin(GL_TRIANGLE_STRIP);
				
				glTexCoord2fv(g.p1);
				glVertex2f(0,0);
				glTexCoord2f(g.p2.x, g.p1.y);
				glVertex2f(g.w, 0);
				glTexCoord2f(g.p1.x, g.p2.y);
				glVertex2f(0, g.h);
				glTexCoord2fv(g.p2);
				glVertex2f(g.w, g.h);
				
				glEnd();
				glEndList();
			}
		}
		
		void Font::draw(float x, float y, std::string text, float r, float g, float b) const
		{
			glMatrixMode(GL_PROJECTION);
			glPushMatrix();
			glLoadIdentity();
			glOrtho(0, 800, 600, 0, -1, 1);
			glMatrixMode(GL_MODELVIEW);

			glPushMatrix();
			glLoadIdentity();
			
			
			fontTexture.bind();
			glTranslatef(x,y,0);
			glColor3f(r,g,b);
			
			for (unsigned i = 0; i < text.length(); i++)
			{
				unsigned char c = text[i];
				if (c < 32 || c > 126) 
					c = '?';
				c -= 32;
				
				const Glyph& g = glyphs[c];
				glCallList(fontBase + c);
				glTranslatef(g.w, 0,0);
			}
			
			glColor3f(1,1,1);
			
			glPopMatrix();

			glMatrixMode(GL_PROJECTION);
			glPopMatrix();
			glMatrixMode(GL_MODELVIEW);
		}
		
		void Font::printf(float x, float y, float r, float g, float b, const char* fmt, ...) const
		{
			char* message = new char[256];
			va_list args;
			va_start(args, fmt);
			vsnprintf(message, 256, fmt, args);
			va_end(args);
			draw(x,y, message, r, g, b);
			
			free(message);	
		}
	
	}
}

